
const canvas = document.getElementById('gameUI');
const context = canvas.getContext('2d');
const images = {};
const list = ['../image/tex1.jpg', '../image/tex2.jpg', '../image/tex3.jpg', '../image/tex4.jpg'];   //添加需要使用到的材质图片路径


//加载绘制图片
function getImageUrl(url) {
    return images[url];
}

//加载一张图片
function loadImage(url, callback) {
    const image = new Image();
    image.src = url;
    image.onload = function () {
        images[url] = image;
        callback();
    }

}

//加载多张图片
function loadMultiImage(list, onSuccess) {
    let current = 0;
    const total = list.length;
    for (const item of list) {
        loadImage(item, function () {
            current++;
            if (current === total) {
                onSuccess();
            }
        })
    }
}

class AbstractRenderer {

    /*
    行为
    */
    $behaviours = [];

    addBehaviour(behaviour) {
        this.$behaviours.push(behaviour);
        behaviour.gameObject = this;
        behaviour.onStart();
    }

    onUpdate(duringTime) {
        for (const behaviour of this.$behaviours) {
            behaviour.onUpdate(duringTime)
        }

        const newBehaviours = [];
        for (const behaviour of this.$behaviours) {
            if (behaviour.$isDestroy) {
                behaviour.onDestroy();
            }
            else {
                newBehaviours.push(behaviour);
            }
        }
        this.$behaviours = newBehaviours;
    }


    removeBehaviour(behaviour) {
        behaviour.$isDestroy = true;

    }

    /**
     * 父节点
     */
    parent = null
    /**
     * x缩放
     */
    scaleX = 1;
    /**
     * 
     * y缩放
     */
    scaleY = 1;
    /**
     * 旋转
     */
    rotation = 0;
    /**
     * x平移
     */
    x = 0;
    /**
     * y平移
     */
    y = 0;


    /**
     * 是否可见
     */
    visible = true;

    /**
     * 透明度
     */
    alpha = 1;

    /**
     * 全局透明度
     */
    $globalAlpha = 1;

    /**
     * 相对矩阵
     */
    $localMatrix;

    /**
     * 绝对矩阵
     */
    $globalMatrix;

    /*移动方向 0为左右，1为上下*/
    movedirection;

    /*回头标志符*/
    isback;

    /*移动的下限和上限*/
    range = [];

    /*移动速度*/
    speed;

    constructor() {
        this.$localMatrix = new Matrix();
        this.$globalMatrix = new Matrix();
    }

    calculateGlobalProperties() {
        this.$localMatrix.updateFromDisplayObject(this.x, this.y, this.scaleX, this.scaleY, this.rotation);
        this.$globalMatrix = matrixAppendMatrix(this.$localMatrix, this.parent.$globalMatrix);
        this.$globalAlpha = this.parent.$globalAlpha * this.alpha;
    }


    //提供可重写的渲染函数接口
    draw(context) {
        this.calculateGlobalProperties();

        context.setTransform(
            this.$globalMatrix.a,
            this.$globalMatrix.b,
            this.$globalMatrix.c,
            this.$globalMatrix.d,
            this.$globalMatrix.tx,
            this.$globalMatrix.ty
        )
        context.globalAlpha = this.$globalAlpha;

        if (this.visible) {
            this.render(context);
        }
    }

    render(context) { }

    move() { }

    hitTest(point) { }
}


class DisplayObjectContainer extends AbstractRenderer {

    children = [];

    addChild(child) {
        const index = this.children.indexOf(child);
        child.parent = this;
        if (index == -1) {
            this.children.push(child);
        }
    }

    removeChild(child) {
        const index = this.children.indexOf(child);
        child.parent = null;
        if (index >= 0) {
            this.children.splice(index, 1);
        }
    }

    //动画的帧刷新
    onUpdate(duringTime) {
        super.onUpdate(duringTime);
        for (let child of this.children) {
            child.onUpdate(duringTime);
        }
    }
    render(context) {
        for (let child of this.children) {
            child.draw(context);
        }
    }

    hitTest(point) {
        for (let i = this.children.length - 1; i >= 0; i--) {
            const child = this.children[i];
            const localMatrix = child.$localMatrix;
            const invertLocalMatrix = invertMatrix(localMatrix);
            //相对于子对象的相对坐标 = 相对于当前对象的相对坐标 * 子对象的相对矩阵的逆矩阵
            const childLocalPoint = pointAppendMatrix(point, invertLocalMatrix);
            const result = child.hitTest(childLocalPoint);
            if (result) {
                return result;
            }
        }
        return null;
    }
}

class RootContainer extends DisplayObjectContainer {

    calculateGlobalProperties() {

    }
}



//绘制背景
class drawBackGoound extends AbstractRenderer {
    color = "black";
    render(context) {
        context.fillStyle = this.color;
        context.fillRect(0, 0, 400, 400);
    }
}

//绘制其他
class drawOther extends AbstractRenderer {
    render(context) {
        //绘制所有豆子
        drawAllBeans(2.2, "pink", 15);

        //绘制外边界
        drawBorder();

        //绘制中心圆角矩形
        drawMRR(200, 200, 80, 60, 'blue', 'white');

        //绘制图片裁剪区域
        //drawClip();
    }
}

//绘制圆角矩形
class drawRR extends AbstractRenderer {
    x = 0;
    y = 0;
    w = 0;
    l = 0;
    color = null;
    render(context) {
      
        context.strokeStyle = this.color;
        context.lineWidth = 2;
        context.beginPath();
        baseRect(0, 0, this.w, this.l);
        context.stroke();
        
    }
}

//绘制下T型地形
class drawDT extends AbstractRenderer {
    x = 0;
    y = 0;
    color = null;
    render(context) {
    context.strokeStyle = this.color;
        context.lineWidth = 2;
        baseDT(0, 0);
        context.stroke();
    }
}

//绘制上T型地形
class drawUT extends AbstractRenderer {
    x = 0;
    y = 0;
    color = null;
    render(context) {
        let Halfw = 30;
        let Halfl = 0;
        context.strokeStyle = this.color;
        context.lineWidth = 2;
        context.beginPath();
        context.moveTo(-Halfw, -10);
        context.lineTo(-20, -10);
        drawRC(-20, -20, 4, 1);
        context.lineTo(-10, -40);
        drawRC(0, -40, 1, 0);
        drawRC(0, -40, 2, 0);
        context.lineTo(10, -20);
        drawRC(20, -20, 3, 1);
        context.lineTo(+Halfw, -10);
        drawRC(Halfw, -Halfl, 2, 0);
        drawRC(Halfw, Halfl, 4, 0);
        context.lineTo(20, Halfl + 10);
        context.lineTo(-Halfw, 10);
        drawRC(-Halfw, 0, 3, 0);
        drawRC(-Halfw, 0, 1, 0);
        context.stroke();
    }
}

//绘制右T型地形
class drawRT extends AbstractRenderer {
    x = 0;
    y = 0;
    color = null;
    render(context) {
        context.strokeStyle = this.color;
        context.lineWidth = 2;
        baseRT(0, 0);
        context.stroke();
    }
}

//绘制左T型地形
class drawLT extends AbstractRenderer {
    x = 0;
    y = 0;
    color = null;
    render(context) {
        context.strokeStyle = this.color;
        context.lineWidth = 2;
        baseLT(0, 0);
        context.stroke();
    }
}


//绘制右凹形
class drawRConcave extends AbstractRenderer {
    x = 0;
    y = 0;
    color = null;
    render(context) {
        let Halfl = 30;
        let Halfw = 30;
        context.strokeStyle = this.color;
        context.lineWidth = 2;
        context.beginPath();
        context.moveTo(-10, Halfl + 10);
        context.lineTo(-10, -Halfl);
        drawRC(0, -Halfl, 1, 0);
        context.lineTo(Halfw + 10, -Halfl - 10);
        drawRC(Halfw + 10, -Halfl, 2, 0);
        drawRC(Halfw + 10, -Halfl, 4, 0);
        context.lineTo(+20, -Halfl + 10);
        drawRC(20, -Halfl + 20, 1, 1);
        context.lineTo(10, Halfl - 10);
        drawRC(20, Halfl - 10, 3, 1);
        context.lineTo(Halfw + 5, Halfl);
        drawRC(Halfw + 5, Halfl + 10, 2, 0);
        drawRC(Halfw + 5, Halfl + 10, 4, 0);
        context.lineTo(0, Halfl + 20);
        drawRC(0, Halfl + 10, 3, 0);
        context.stroke();
    }

}

//绘制左凹形
class drawLConcave extends AbstractRenderer {
    x = 0;
    y = 0;
    color = null;
    render(context) {
        let Halfl = 30;
        let Halfw = 30;
        context.strokeStyle = this.color;
        context.lineWidth = 2;
        context.beginPath();
        context.moveTo(10, Halfl + 10);
        context.lineTo(10, -Halfl);
        drawRC(0, -Halfl, 2, 1);
        context.lineTo(-Halfw - 10, -Halfl - 10);
        drawRC(-Halfw - 10, -Halfl, 1, 1);
        drawRC(-Halfw - 10, -Halfl, 3, 1);
        context.lineTo(-20, -Halfl + 10);
        drawRC(-20, -Halfl + 20, 2, 0);
        context.lineTo(-10, Halfl - 10);
        drawRC(-20, Halfl - 10, 4, 0);
        context.lineTo(-Halfw - 5, Halfl);
        drawRC(-Halfw - 5, Halfl + 10, 1, 1);
        drawRC(-Halfw - 5, Halfl + 10, 3, 1);
        context.lineTo(0, Halfl + 20);
        drawRC(0, Halfl + 10, 4, 1);
        context.stroke();
    }
}

//绘制右直角型
class drawRTR extends AbstractRenderer {
    x = 0;
    y = 0;
    color = null;
    render(context) {
        let Halfl = 20;
        let Halfw = 30;
        context.strokeStyle = this.color;
        context.lineWidth = 2;
        context.beginPath();
        context.moveTo(10, -Halfl);
        context.lineTo(10, Halfl);
        drawRC(0, Halfl, 4, 0);
        drawRC(0, Halfl, 3, 0);
        context.lineTo(-10, -Halfl + 20);
        drawRC(-20, -Halfl + 20, 2, 1);
        context.lineTo(-Halfw, -Halfl + 10);
        drawRC(-Halfw, -Halfl, 3, 0);
        drawRC(-Halfw, -Halfl, 1, 0);
        context.lineTo(0, -Halfl - 10);
        drawRC(0, -Halfw + 10, 2, 0);
        context.stroke();
    }

}

//绘制左直角型
class drawLTR extends AbstractRenderer {
    x = 0;
    y = 0;
    color = null;
    render(context) {
        let Halfl = 20;
        let Halfw = 30;
        context.strokeStyle = this.color;
        context.lineWidth = 2;
        context.beginPath();
        context.moveTo(-10, -Halfl);
        context.lineTo(-10, Halfl);
        drawRC(0, Halfl, 3, 1);
        drawRC(0, Halfl, 4, 1);
        context.lineTo(10, -Halfl + 20);
        drawRC(20, -Halfl + 20, 1, 0);
        context.lineTo(Halfw, -Halfl + 10);
        drawRC(Halfw, -Halfl, 4, 1);
        drawRC(Halfw, -Halfl, 2, 1);
        context.lineTo(0, -Halfl - 10);
        drawRC(0, -Halfw + 10, 1, 1);
        context.stroke();
    }

}

//绘制吃豆人
class drawPlayer extends AbstractRenderer {
    x = 0;
    y = 0;
    name;

    constructor(name) {
        super();
        this.name = name;
    }

    color = null;
    render(context) {
        context.beginPath();
        let startAngle = (Math.PI / 180) * 330; // 开始点
        let endAngle = (Math.PI / 180) * 30;  //结束点
        context.arc(0, 0, 7, startAngle, endAngle, true); //false是顺时针clockwise绘制，true是逆时针anticlockwise绘制。
        context.lineTo(-5, 0);
        context.fillStyle = this.color;
        context.fill();
    }

    hitTest(point,duringTime) {
        const rectangle = { x: 0, y: 0, width: 20, height: 20 };
        const result = checkPointInRectangle(point, rectangle);

        if (result) {
            console.log(this.name + ` is clicked!`)
            //this.parent.x += 1;
            return this;
            /*let a=this.parent;
            while(a.parent)
            {
               a =a.parent;
               console.log(1);
            }
            a.x += 1;*/
        }
        else {
            return null;
        }
    }
}

//绘制小怪物
class drawImp extends AbstractRenderer {
    x = 0;
    y = 0;
    righteye = 0;
    lefteye = 0;
    color = null;


    constructor(name) {
        super();
        this.name = name;
    }

    //绘制身体
    render(context) {
        context.fillStyle = this.color;
        context.beginPath();
        context.moveTo(-10, 10);
        context.lineTo(-10, 0);
        context.arc(0, 0, 10, Math.PI, 0, false);
        context.lineTo(10, 10);
        context.lineTo(6.66, 12);
        context.lineTo(3.33, 10);
        context.lineTo(0, 12);
        context.lineTo(-3.33, 10);
        context.lineTo(-6.66, 12);
        context.lineTo(-10, 10);
        context.fill();
        //context.bezierCurveTo(83,94,89,88,97,88);      //贝塞尔曲线，分二次曲线quadraticCurveTo()和三次曲线bezierCurveTo()，1个控制点和1个结束点，2个控制点和1个结束点，起始点为上次操作的延续位置。

        //绘制眼白
        context.fillStyle = "white";
        context.beginPath();
        context.arc(4.5, 0, 4, 0, Math.PI * 2, true);
        context.fill();
        context.beginPath();
        context.arc(-4.5, 0, 4, 0, Math.PI * 2, true);
        context.fill();

        //绘制眼珠
        context.fillStyle = "black";
        context.beginPath();
        context.arc(this.righteye, 1.5, 1.8, 0, Math.PI * 2, true); //右眼珠
        context.fill();
        context.beginPath();
        context.arc(this.lefteye, 1.5, 1.8, 0, Math.PI * 2, true);  //左眼珠
        context.fill();
    }

    hitTest(point) {
        const rectangle = { x: 0, y: 0, width: 25, height: 25 };
        const result = checkPointInRectangle(point, rectangle);

        if (result) {
            console.log(this.name + " is clicked!");
            return this;
        }
        else {
            return null;
        }
    }

    move() {
        if (this.movedirection === 1) {
            if (this.isback === false) {
            this.y += this.speed;
                if (this.y >= this.range[1])
                    this.isback = true;
            }
            else {
            this.y -= this.speed;
                if (this.y <= this.range[0])
                    this.isback = false;
            }
        }
        else if (this.movedirection === 0) {
            if (this.isback === false) {
            this.x += this.speed;
                if (this.x >= this.range[1])
                    this.isback = true;
            }
            else {
            this.x -= this.speed;
                if (this.x <= this.range[0])
                    this.isback = false;
            }
        }
    }
}

//绘制图片
class ImageRenderer extends AbstractRenderer {

    x = 0;
    y = 0;
    w = 0;
    l = 0;
    image = null;

    //重写接口函数
    render(context) {
        if (this.image) {
            context.drawImage(this.image, 0, 0, this.w, this.l);
        }

    }
}


class Behaviour {


    onStart() {

    }

    onUpdate() {

    }

    onDestroy() {

    }
}


class drawText extends AbstractRenderer {

    //初始值
    x = 0;
    y = 0;
    color = 'black';
    text = 'helloworld';

    render(context) {
        context.font = "bold 18px serif"   //注意在字符串中应用变量的格式，不要漏了加号
        context.fillStyle = this.color;
        context.fillText(this.text, 0, 0);
    }

}


//引擎核心
class GameEngineCore {

    onStart;

    onUpdate;

    root;

    //renderList = [];

    lastIterationTime = 0;

    lastAdvancedTime = 0;

    fps = 60;


    start() {
        this.root = new RootContainer();
        loadMultiImage(['../image/tex1.jpg', '../image/tex2.jpg', '../image/tex3.jpg', '../image/tex4.jpg'], this.onStart)
        requestAnimationFrame(this.onFrame.bind(this));
    }

    hitTest(point) {
        let result = this.root.hitTest(point);
        while (result) {
            if (result.onClick) {
                result.onClick();
                console.log(this.name);
            }
            result = result.parent;
        }
    }

    onFrame(advancedTime) {
        context.save();
        context.clearRect(0, 0, 400, 400)

        const duringTime = advancedTime - this.lastAdvancedTime;
        this.lastAdvancedTime = advancedTime;
        this.lastIterationTime += duringTime;
        const frameTime = 1000 / this.fps;

        while (this.lastIterationTime >= frameTime) {
            this.lastIterationTime -= frameTime;
            this.onUpdate(duringTime);
            this.root.onUpdate(duringTime);
        }

        /*
        //执行每个绘制对象中的draw方法，对渲染列表中的对象进行绘制
        for (let item of this.renderList) {
            item.draw(context);
        }
        */
        this.root.draw(context);
        context.restore();
        requestAnimationFrame(this.onFrame.bind(this));
    }

}





